﻿(*                  FnSharp              

   Base class library extensions and frameworks aimed 
   specifically at improving F# developers lives!

   Written by: Huw Simpson
   License: Microsoft Public License (Ms-PL) 
   Available at: http://fnsharp.codeplex.com

*)
namespace FnSharp.Bcl.Core

    open System

    [<RequireQualifiedAccess>]
    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
    module Option =
        /// Default to a supplied value when the option is none.
        [<CompiledName("DefaultTo")>]
        let inline defaultTo defaultValue opt =
            match opt with
            | None -> defaultValue
            | Some v -> v

        /// Default to a value returned by a function when the option is none.
        [<CompiledName("DefaultToF")>]
        let inline defaultToF f opt =
            match opt with
            | None -> f ()
            | Some v -> v

        /// Map the option value, or default to a supplied value when the option is none.
        [<CompiledName("MapOrDefaultTo")>]
        let inline mapOrDefaultTo map defaultValue opt =
            match opt with
            | None -> defaultValue
            | Some v -> map v

        /// Map the option value, or default to a value returned by a function when the option is none
        [<CompiledName("MapOrDefaultToF")>]
        let inline mapOrDefaultToF map f opt =
            match opt with
            | None -> f ()
            | Some v -> map v

        /// Map the option value, or default to the generic default when the option is none.
        [<CompiledName("MapOrDefault")>]
        let inline mapOrDefault map opt =
            opt |> mapOrDefaultTo map Unchecked.defaultof<_>

        /// Create an option from a class instance, null is mapped to None.
        [<CompiledName("OfObject")>]
        let inline ofObject ref =
            match ref with
            | null -> None
            | o -> Some (o)

        /// Map a boolean value to an option with a supplied value.
        [<CompiledName("OfBool")>]
        let inline ofBool value isTrue =
            if isTrue then Some (value) else None
        
        /// Map a boolean value to an option with a supplied value.
        [<CompiledName("OfBool2")>]
        let inline ofBool2 (isTrue, value) =
            isTrue |> ofBool (value)

        /// Map an inverted boolean value to an option with a supplied value.
        [<CompiledName("OfBoolInv")>]
        let inline ofBoolInv value isTrue =
            not (isTrue) |> ofBool (value)

        /// Map an inverted boolean value to an option with a supplied value.
        [<CompiledName("OfBoolInv2")>]
        let inline ofBoolInv2 (isTrue, value) =
            not(isTrue) |> ofBool (value)

        /// Map a boolean value to an option with a supplied value returned by a function.
        [<CompiledName("OfBoolF")>]
        let inline ofBoolF getValue isTrue =
            if isTrue then Some (getValue ()) else None

        /// Map an inverted boolean value to an option with a supplied value returned by a function.
        [<CompiledName("OfBoolInvF")>]
        let inline ofBoolInvF getValue isTrue =
            not (isTrue) |> ofBoolF (getValue)

        /// Map a boolean value to an option with a supplied value returned by a function.
        [<CompiledName("OfBoolF2")>]
        let inline ofBoolF2 getValue action isTrue =
            if isTrue then 
                let value = getValue ()
                action value
                Some (value) 
            else None

        /// Map an inverted boolean value to an option with a supplied value returned by a function.
        [<CompiledName("OfBoolInvF2")>]
        let inline ofBoolInvF2 getValue action isTrue =
            not (isTrue) |> ofBoolF2 getValue action

